package atguigu.crowd.mvc.config;

import atguigu.crowd.constant.CrowdConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
@EnableWebSecurity
// 启用全局方法权限控制功能，并且设置 prePostEnabled = true。保证@PreAuthority、@PostAuthority、@PreFilter、@PostFilter 生效
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebAppSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 临时使用内存
        /*auth
                .inMemoryAuthentication()
                .withUser("tom").password("123123")         //设置账号密码
                .roles("学徒")                                         //设置角色
                .and()
                .withUser("jerry").password("456456")       //设置另一个账号密码
                .roles("大师")
                .authorities("内门弟子");                            //设置权限*/

        // 使用数据库
        auth
                .userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
    }

    @Override
    protected void configure(HttpSecurity security) throws Exception {
        security
                .authorizeRequests()                                       // 对请求进行授权
                .antMatchers("/admin/to/login/page.html")    // 针对登录页进行设置
                .permitAll()                                               // 无条件访问
                .antMatchers("/bootstrap/**")                // 针对静态资源进行设置，无条件访问
                .permitAll()                                               // 针对静态资源进行设置，无条件访问
                .antMatchers("/crowd/**")                    // 针对静态资源进行设置，无条件访问
                .permitAll()                                               // 针对静态资源进行设置，无条件访问
                .antMatchers("/css/**")                      // 针对静态资源进行设置，无条件访问
                .permitAll()                                               // 针对静态资源进行设置，无条件访问
                .antMatchers("/fonts/**")                    // 针对静态资源进行设置，无条件访问
                .permitAll()                                               // 针对静态资源进行设置，无条件访问
                .antMatchers("/img/**")                      // 针对静态资源进行设置，无条件访问
                .permitAll()                                               // 针对静态资源进行设置，无条件访问
                .antMatchers("/jquery/**")                   // 针对静态资源进行设置，无条件访问
                .permitAll().antMatchers("/layer/**")        // 针对静态资源进行设置，无条件访问
                .permitAll()                                               // 针对静态资源进行设置，无条件访问
                .antMatchers("/script/**")                   // 针对静态资源进行设置，无条件访问
                .permitAll()                                               // 针对静态资源进行设置，无条件访问
                .antMatchers("/ztree/**")                    // 针对静态资源进行设置，无条件访问
                .permitAll()
                .antMatchers("/admin/get/page.html")         // 针对分页显示 Admin 数据设定访问控制
                .hasRole("部长")                                          // 要求具备经理角色
                .antMatchers("/role/to/page.html")          // 针对角色管理模块
                .hasRole("经理")                                          // 需要经理角色
//                .antMatchers("/menu/to/page.html", "/admin/get/page.html", "/role/to/page.html")
//                .hasRole("总经理")                                        // 总经理什么都可以访问


                .anyRequest()                                           // 对于其他请求
                .authenticated()                                        // 需要登录权限
                .and()
                .formLogin()                                    // 开启表单登录的功能
                .loginPage("/admin/to/login/page.html")         // 指定登录页面
                .loginProcessingUrl("/security/do/login.html")  // 指定处理登录请求的地址
                .defaultSuccessUrl("/admin/to/main/page.html")  // 指定登录成功后前往的地址
                .usernameParameter("loginAcct")                 // 账号的请求参数
                .passwordParameter("userPswd")                  // 密码的请求参数
                .and()
                .csrf()                                         // 跨站请求访问
                .disable()                                      // 禁用
                .logout()
                .logoutUrl("/admin/do/logout.html")
                .logoutSuccessUrl("/admin/to/login/page.html")
                .and()
                .exceptionHandling()
                .accessDeniedHandler((httpServletRequest, httpServletResponse, e) -> {
                    httpServletRequest.setAttribute("exception", new Exception(CrowdConstant.MESSAGE_ACCESS_DENIED));
                    httpServletRequest.getRequestDispatcher("/WEB-INF/system-error.jsp").forward(httpServletRequest, httpServletResponse);
                })
                ;

    }

}
